using HZY.Framework.DependencyInjection;
using IoTClient.Common.Enums;
using IoTClient.Enums;
using Long.BLL;
using Long.Helper;
using Long.Model;
using Masuit.Tools;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MiniExcelLibs;
using SixLabors.ImageSharp.ColorSpaces;
using Sunny.UI;
using System.Threading.Tasks;
using System.Timers;

namespace Long.SpraySCADA
{
    public partial class FrmMain : UIHeaderAsideMainFooterFrame, ISingletonSelfDependency
    {
        private bool plcIsConnected = false;
        private CancellationTokenSource cts = new CancellationTokenSource();
        private readonly UserManager _userManager;
        private readonly AuthManager _authManager;
        private readonly DataManager _dataManager;

        //标识是否第一次启动
        private bool isFirst = true;
        private bool isConnectFirst = true;
        //主界面设备监控
        private System.Timers.Timer timer_Main = new System.Timers.Timer(1000);

        //调用注入的 日志 类
        private readonly ILogger<FrmMain> _logger;

        // 页面控件的字典，用于管理各个模块的控件
        private Dictionary<string, Control> pageControls = new Dictionary<string, Control>
        {
            { "控制模块", Globals.ServiceProvider.GetRequiredService<PageTotalEquipmentControl>() },
            { "用户模块", Globals.ServiceProvider.GetRequiredService<PageUserManage>() },
            { "权限模块", Globals.ServiceProvider.GetRequiredService<PageAuthManage>() },
            { "监控模块", Globals.ServiceProvider.GetRequiredService<PageEquipmentMonitor>() },
            { "监控模块1", Globals.ServiceProvider.GetRequiredService<PageEquipmentMonitor1>() },
            { "监控模块2", Globals.ServiceProvider.GetRequiredService<PageEquipmentMonitor2>() },
            { "配方模块", Globals.ServiceProvider.GetRequiredService<PageRecipeManage>() },
            { "日志模块", Globals.ServiceProvider.GetRequiredService<PageLogManage>() },
            { "报表模块", Globals.ServiceProvider.GetRequiredService<PageReportManage>() },
            { "图表模块", Globals.ServiceProvider.GetRequiredService<PageChartManage>() },
            { "参数模块", Globals.ServiceProvider.GetRequiredService<PageSystemParameterSet>() }
        };

        private List<string> AlarmInfos = new List<string>();
        #region 初始化
        public FrmMain(ILogger<FrmMain> _logger, UserManager userManager, AuthManager authManager, DataManager dataManager)
        {
            InitializeComponent();
            this._logger = _logger;
            this._userManager = userManager;
            this._authManager = authManager;
            this._dataManager = dataManager;

           // this.lbl_User.Text = "访客";

            //Init();

            this.Closed += (sender, e) =>
            { //匿名委托，手动关闭PLC连接
                Globals.SiemensClient.Close();
            };
        }

        public override void Init()
        {

            //测试创建 ini
            //Globals.IniFile.Write("PLC", "DataAddress", Application.StartupPath + "\\PLCAddress\\PLC_Var_Config.xlsx");
            InitConfig();
            IniAsideUI();
            InitHeaderUI();
            IniPLCClient();
            IniOther();
        }

        /// <summary>
        /// 初始化 Timer
        /// </summary>
        private void IniOther()
        {
            if (Globals.SaveDay != "不清理")
            {
                DelFile.DeleteFolder(Globals.DelFilePath, Globals.SaveDay.ToInt());
            }

            
            timer_Main.Elapsed += Timer_Main_Elapsed;
            timer_Main.Start();
            
        }

        private  void Timer_Main_Elapsed(object? sender, ElapsedEventArgs e)
        {
            if (Globals.SiemensClient.Connected)
            {
                if (this.InvokeRequired)
                {
                    this.Invoke((Delegate)( async() =>
                    {
                        //跨线程操作，必须线程安全
                        //数据监控信息
                        this.lbl_ProducteCount.Text = Globals.DataDicPLC[this.lbl_ProducteCount.TagString].ToString();
                        this.lbl_BadCount.Text = Globals.DataDicPLC[this.lbl_BadCount.TagString].ToString();
                        this.lbl_Beat.Text = Globals.DataDicPLC[this.lbl_Beat.TagString].ToString();
                        this.lbl_TotalAlarm.Text = Globals.DataDicPLC[this.lbl_TotalAlarm.TagString].ToString();
                        this.lbl_Temperature.Text = Globals.DataDicPLC[this.lbl_Temperature.TagString].ToString()+ " ℃";
                        this.lbl_Humidness.Text = Globals.DataDicPLC[this.lbl_Humidness.TagString].ToString() + " %";
                        //设备监控信息--CPU和内存
                        string CPUstr = RuntimeStatusHelper.DataManager.GetCpuUtilization();
                        string MemoryStr = RuntimeStatusHelper.DataManager.GetMemoryUtilization().Replace("G", "");
                        string NeiResult = (double.Parse(MemoryStr.Split('/')[0]) / double.Parse(MemoryStr.Split('/')[1]) * 100).ToString("f1") + "%";
                        this.lbl_CPUInformation.Text = double.Parse(CPUstr).ToString("f1") + "%";
                        this.lbl_MemoryInformation.Text = NeiResult;

                        //时间
                        lbl_Time.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                        //报警信息
                        List<string> alarms = CheckAlarms(AlarmInfos);
                        string alarmStr = string.Join(",", alarms);
                        if (string.IsNullOrEmpty(alarmStr))
                        {
                            this.st_AlarmInfo.Text = "系统正常";
                            this.st_AlarmInfo.ForeColor = Color.Blue;
                            this.led_ProducteState.On = true;
                            this.led_ProducteState.Color = Color.LightGreen;
                            this.led_ProducteState.Blink= false;
                            
                        }
                        else
                        {
                            this.st_AlarmInfo.Text = alarmStr;
                            this.st_AlarmInfo.ForeColor = Color.Red;
                            this.led_ProducteState.On = false;
                            this.led_ProducteState.Color = Color.Red;
                            this.led_ProducteState.BlinkInterval = 500;
                            this.led_ProducteState.Blink = true;
                        }

                        //保存数据
                        DataAddDto dto = new DataAddDto();
                        dto.InsertTime = DateTime.Now;

                        foreach (var item in Globals.SaveDataList)
                        {
                            //筛选出需要保存的数据
                            string type = typeof(DataAddDto).GetProperty(item).PropertyType.Name;
                            if(type == "String")
                            {
                                dto.GetType().GetProperty(item).SetValue(dto, Globals.DataDicPLC[item].ToString());
                            }
                        }

                        //保存数据到数据库
                        BaseResult res = await _dataManager.AddDataAsyncManager(dto);
                        if(res.ResultStatus == SystemEnums.ResultStatus.Fail)
                        {
                            LogExtension.ShowMessage("数据保存失败！", Microsoft.Extensions.Logging.LogLevel.Error);
                        }
                    }));
                }
                else
                {
                    this.lbl_ProducteCount.Text = Globals.DataDicPLC[this.lbl_ProducteCount.TagString].ToString();
                    this.lbl_BadCount.Text = Globals.DataDicPLC[this.lbl_BadCount.TagString].ToString();
                    this.lbl_Beat.Text = Globals.DataDicPLC[this.lbl_Beat.TagString].ToString();
                    this.lbl_TotalAlarm.Text = Globals.DataDicPLC[this.lbl_TotalAlarm.TagString].ToString();
                    this.lbl_Temperature.Text = Globals.DataDicPLC[this.lbl_Temperature.TagString].ToString() + " ℃";
                    this.lbl_Humidness.Text = Globals.DataDicPLC[this.lbl_Humidness.TagString].ToString() + " %";
                }

                if (isFirst)
                {
                    isFirst = false;
                    Globals.ServiceProvider.GetRequiredService<FromStartLoad>().CloseFormThread();
                }
            }
        }

        private List<string> CheckAlarms(List<string> alarmInfos)
        {
            List<string> alarms = new List<string>();
            foreach (var item in alarmInfos)
            {
                if (Globals.DataDicPLC[item].ToString() == "1")
                {
                    alarms.Add(item);
                }
            }
            return alarms;
        }

        /// <summary>
        /// 初始化 Ini 配置
        /// </summary>
        private void InitConfig()
        {
            //读取表的地址
            Globals.PlcVarConfigPath = Globals.IniFile.Read("PLC", "DataAddress", Application.StartupPath + "PLCAddress\\PLC_Var_Config.xlsx");

            //读取PLC的地址
            Globals.IpAddress = Globals.IniFile.Read("PLC", "IPAddress", "127.0.0.1");
            //读取PLC的端口
            Globals.Port = int.Parse(Globals.IniFile.Read("PLC", "Port", "102"));
            //读取PLC的CPU类型
            Globals.CpuType = Enum.Parse<SiemensVersion>(Globals.IniFile.Read("PLC", "CpuType", "S7_1200"));
            //读取PLC机架号
            Globals.Rack = byte.Parse(Globals.IniFile.Read("PLC", "Rack", "0"));
            //读取PLC卡槽号
            Globals.Slot = byte.Parse(Globals.IniFile.Read("PLC", "Slot", "0"));
            //读取PLC超时时间
            Globals.ConnectTimeOut = int.Parse(Globals.IniFile.Read("PLC", "超时时间", "3000"));
            //读取PLC数据循环时间
            Globals.ReadTimeInterval = int.Parse(Globals.IniFile.Read("PLC", "循环读取时间", "500"));
            //读取PLC重连时间
            Globals.ReConnectTimeInterval = int.Parse(Globals.IniFile.Read("PLC", "重连时间", "3000"));
            //删除文件夹
            Globals.DelFilePath = Globals.IniFile.Read("系统参数", "删除文件路径", Path.Combine(Application.StartupPath, "Logs"));
            Globals.SaveDay = Globals.IniFile.Read("系统参数", "保存天数", "7天");
            //软件版本
            Globals.SoftwareVersion = Globals.IniFile.Read("系统参数", "软件版本", "V1.0.0");
            Globals.SYTime = Globals.IniFile.Read("系统参数", "试用时间", "100");
            
            _logger.LogInformation("初始化 Ini 配置");
        }

        /// <summary>
        /// 初始化PLC客户端
        /// </summary>
        private void IniPLCClient()
        {

            //导入PLC变量
            var plcAddressList = MiniExcel.Query<PLCVarConfigModel>(Globals.PlcVarConfigPath).ToList();
            //初始化PLC客户端  西门子
            Globals.SiemensClient = new IoTClient.Clients.PLC.SiemensClient(Globals.CpuType, Globals.IpAddress, Globals.Port, Globals.Rack, Globals.Slot, Globals.ConnectTimeOut);
            //连接PLC
            var connectResult = Globals.SiemensClient.Open();
            if (connectResult.IsSucceed)
            {
                plcIsConnected = true;
                this.led_PlcState.On = true;
            }
            else
            {
                plcIsConnected = false;
                this.led_PlcState.On = false;
            }

            for (int i = 0; i < plcAddressList.Count; i++)
            {
                //初始化PLC变量地址字典  <地址，类型>
                Globals.ReadDicPLC.Add(plcAddressList[i].PLCAddress, Enum.Parse<DataTypeEnum>(plcAddressList[i].Type, true));
                //初始化PLC变量写入   <名称，地址>
                Globals.WriteDicPLC.Add(plcAddressList[i].Name, plcAddressList[i].PLCAddress);
                //初始化PLC变量读取   <名称，值>
                Globals.DataDicPLC.Add(plcAddressList[i].Name, "NA");
                //初始化PLC保存数据的变量集合
                if (plcAddressList[i].Save.ToLower()=="true")
                {
                    Globals.SaveDataList.Add(plcAddressList[i].Name);
                }
                //添加报警
                if (plcAddressList[i].Name.EndsWith("报警") && !plcAddressList[i].Name.Contains("累计报警"))
                {
                    AlarmInfos.Add(plcAddressList[i].Name);
                }

            }
            _logger.LogInformation("初始化 PLC 客户端成功");
            try
            {
                Task.Run(async () =>
                {
                    while (!cts.IsCancellationRequested)
                    {
                        if (plcIsConnected)
                        {
                            //读取PLC值
                            var readResult = Globals.SiemensClient.BatchRead(Globals.ReadDicPLC);
                            if (readResult.IsSucceed)
                            {
                                for (int j = 0; j < plcAddressList.Count; j++)
                                {
                                    //逐一赋值，以达到名称和值绑定
                                    Globals.DataDicPLC[plcAddressList[j].Name] = readResult.Value[plcAddressList[j].PLCAddress];
                                }
                            }
                            else
                            {
                                plcIsConnected = false;
                                Globals.SiemensClient.Close();
                                this.Invoke(() =>
                                {//跨线程，必须线程安全
                                    this.led_PlcState.On = false;
                                });
                            }
                            await Task.Delay(Globals.ReadTimeInterval);
                        }
                        else
                        {
                            if (isConnectFirst)
                            {
                                //第一次重连失败，关闭缓存程序
                                isConnectFirst = false;
                                Globals.ServiceProvider.GetRequiredService<FromStartLoad>().CloseFormThread();
                            }
                            //第一次未连接上，重连
                            var reConnectResult = Globals.SiemensClient.Open();
                            if (reConnectResult.IsSucceed)
                            {
                                plcIsConnected = true;
                                this.Invoke(() =>
                                {//跨线程，必须线程安全
                                    this.led_PlcState.On = true;
                                });
                            }
                            else
                            {
                                plcIsConnected = false;
                                Globals.SiemensClient.Close();
                                this.Invoke(() =>
                                {//跨线程，必须线程安全
                                    this.led_PlcState.On = false;
                                });
                                //重连失败，等待一段时间后重试
                                await Task.Delay(Globals.ReConnectTimeInterval);
                            }
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                throw;
            }
        }

        /// <summary>
        /// 初始化侧边栏菜单
        /// </summary>
        private void IniAsideUI()
        {
            //设置关联
            Aside.TabControl = MainTabControl;

            //设置初始页面索引（关联页面，唯一不重复即可）
            int pageIndex = 1000;

            TreeNode parent0 = Aside.CreateNode("控制模块", 361461, 34, pageIndex);
            Aside.CreateChildNode(parent0, AddPage(Globals.ServiceProvider.GetRequiredService<PageTotalEquipmentControl>(), ++pageIndex));

            TreeNode parent1 = Aside.CreateNode("用户模块", 61447, 34, pageIndex);
            Aside.CreateChildNode(parent1, AddPage(Globals.ServiceProvider.GetRequiredService<PageUserManage>(), ++pageIndex));
            Aside.CreateChildNode(parent1, AddPage(Globals.ServiceProvider.GetRequiredService<PageAuthManage>(), ++pageIndex));

            TreeNode parent2 = Aside.CreateNode("监控模块", 560066, 34, pageIndex);
            Aside.CreateChildNode(parent2, AddPage(Globals.ServiceProvider.GetRequiredService<PageEquipmentMonitor>(), ++pageIndex));
            Aside.CreateChildNode(parent2, AddPage(Globals.ServiceProvider.GetRequiredService<PageEquipmentMonitor1>(), ++pageIndex));
            Aside.CreateChildNode(parent2, AddPage(Globals.ServiceProvider.GetRequiredService<PageEquipmentMonitor2>(), ++pageIndex));

            TreeNode parent3 = Aside.CreateNode("配方模块", 162677, 34, pageIndex);
            Aside.CreateChildNode(parent3, AddPage(Globals.ServiceProvider.GetRequiredService<PageRecipeManage>(), ++pageIndex));

            TreeNode parent4 = Aside.CreateNode("日志模块", 57557, 34, pageIndex);
            Aside.CreateChildNode(parent4, AddPage(Globals.ServiceProvider.GetRequiredService<PageLogManage>(), ++pageIndex));

            TreeNode parent5 = Aside.CreateNode("报表模块", 57586, 34, pageIndex);
            Aside.CreateChildNode(parent5, AddPage(Globals.ServiceProvider.GetRequiredService<PageReportManage>(), ++pageIndex));

            TreeNode parent6 = Aside.CreateNode("图表模块", 61950, 34, pageIndex);
            Aside.CreateChildNode(parent6, AddPage(Globals.ServiceProvider.GetRequiredService<PageChartManage>(), ++pageIndex));

            TreeNode parent7 = Aside.CreateNode("参数模块", 559576, 34, pageIndex);
            Aside.CreateChildNode(parent7, AddPage(Globals.ServiceProvider.GetRequiredService<PageSystemParameterSet>(), ++pageIndex));

            //显示默认界面
            Aside.SelectFirst();
            _logger.LogInformation("初始化 侧边菜单栏");
        }

        /// <summary>
        /// 初始化头部菜单栏
        /// </summary>
        private void InitHeaderUI()
        {
            //设置关联
            Header.TabControl = MainTabControl;

            //通过图标识别功能
            Header.Nodes.Add("");
            Header.Nodes.Add("");
            Header.Nodes.Add("");
            Header.SetNodeSymbol(Header.Nodes[0], 558295, 34);
            Header.SetNodeSymbol(Header.Nodes[1], 61489, 34);
            Header.SetNodeSymbol(Header.Nodes[2], 557925, 34);

            var styles = UIStyles.PopularStyles();
            foreach (UIStyle style in styles)
            {
                Header.CreateChildNode(Header.Nodes[0], style.DisplayText(), style.Value());
            }

            //获取枚举FontsType的所有字体名称
            for (int i = 0; i < Enum.GetValues(typeof(SystemEnums.FontsType)).Length; i++)
            {
                Header.CreateChildNode(Header.Nodes[1], Enum.GetName(typeof(SystemEnums.FontsType), i), i + 1);
            }

            //获取枚举FontSize的所有字体大小  75-125的范围 75 80 85 90 95 100 105 110 115 120 125
            for (int i = 75; i <= 125; i += 5)
            {
                Header.CreateChildNode(Header.Nodes[2], i.ToString(), i);
            }

            _logger.LogInformation("初始化 头部菜单栏");
        }

        #endregion

        /// <summary>
        /// 切换风格
        /// </summary>
        /// <param name="itemText"></param>
        /// <param name="menuIndex"></param>
        /// <param name="pageIndex"></param>
        private void Header_MenuItemClick(string itemText, int menuIndex, int pageIndex)
        {
            switch (menuIndex)
            {
                case 0:
                    UIStyle style = (UIStyle)pageIndex;
                    if (pageIndex < UIStyle.Colorful.Value())
                    {
                        StyleManager.Style = style;

                        if (UIExtension.SetStyleManager != null)
                        {
                            UIExtension.SetStyleManager(StyleManager);
                        }
                    }
                    break;

                case 1:
                    UIStyles.DPIScale = true;
                    UIStyles.GlobalFont = true;
                    UIStyles.GlobalFontName = itemText;

                    UIStyles.GlobalFontScale = SystemConsts.DefaultFontScale;
                    UIStyles.SetDPIScale();
                    break;

                case 2:
                    UIStyles.GlobalFontScale = int.Parse(itemText);
                    UIStyles.SetDPIScale();
                    break;

                default:

                    break;
            }
        }

        #region 最小化和关闭系统
        private void lbl_Min_Click(object sender, EventArgs e)
        {
            //最小化
            this.WindowState = FormWindowState.Minimized;
        }

        private void lbl_Exit_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        #endregion

        #region 无边框拖动

        private Point mPoint;
        private void uiPanel1_MouseDown(object sender, MouseEventArgs e)
        {
            mPoint = new Point(e.X, e.Y);
        }

        private void uiPanel1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.Location = new Point(this.Location.X + e.X - mPoint.X, this.Location.Y + e.Y - mPoint.Y);
            }
        }
        #endregion

        private void pictureBox2_Click(object sender, EventArgs e)
        {
            //把Aside折叠起来
            Aside.CollapseAll();
            Aside.SelectFirst();

            FrmLogin frmLogin = Globals.ServiceProvider.GetRequiredService<FrmLogin>();
            frmLogin.ShowDialog();
            if (frmLogin.IsLogin)
            {
                //更新登录用户
                this.lbl_User.Text = frmLogin.UserName;
                foreach (Control control in pageControls.Values)
                {
                    control.Enabled = true;
                }
            }
        }

        private async void Aside_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            string moduleName = e.Node.Text;

            string userName = this.lbl_User.Text;  //通过name拿到用户权限
            BaseResult<UserQueryResultDto> roleRes = await _userManager.GetUserAuthAsyncManager(new UserAuthQueryDto() { UserName = userName });
            if (roleRes.ResultStatus == SystemEnums.ResultStatus.Success)
            {
                if (roleRes.Data[0].Role != "管理员")
                {
                    //管理员默认所有权限，此处限制权限
                    BaseResult<AuthRequestDto> authRes = await _authManager.GetAuthAsync(new AuthQueryDto() { Role = roleRes.Data[0].Role });
                    if (authRes.ResultStatus == SystemEnums.ResultStatus.Success)
                    {
                        //通过角色拿到权限后

                        UpdateControlAccess(moduleName, authRes.Data[0], pageControls);
                    }
                }
            }
        }

        private void UpdateControlAccess(string moduleName, AuthRequestDto authDto, Dictionary<string, Control> pageControls)
        {
            switch (moduleName)
            {
                case "控制模块":
                    pageControls["控制模块"].Enabled = authDto.ControlModule;
                    break;

                case "用户模块":
                    pageControls["用户模块"].Enabled = false;
                    pageControls["权限模块"].Enabled = false;
                    break;

                case "监控模块":
                    pageControls["监控模块"].Enabled = authDto.MonitorModule;
                    pageControls["监控模块1"].Enabled = authDto.MonitorModule;
                    pageControls["监控模块2"].Enabled = authDto.MonitorModule;
                    break;

                case "配方模块":
                    pageControls["配方模块"].Enabled = authDto.RecipeModule;
                    break;

                case "日志模块":
                    pageControls["日志模块"].Enabled = authDto.LogModule;
                    break;

                case "报表模块":
                    pageControls["报表模块"].Enabled = authDto.ReportModule;
                    break;

                case "图表模块":
                    pageControls["图表模块"].Enabled = authDto.ChartModule;
                    break;

                case "参数模块":
                    pageControls["参数模块"].Enabled = authDto.ParamModule;
                    break;

                default:
                    break;
            }
        }

        private void FrmMain_Shown(object sender, EventArgs e)
        {
            Globals.ServiceProvider.GetRequiredService<FromStartLoad>().OpenFormThread();
           Init();
        }


        #region 窗体切换卡顿
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams paras = base.CreateParams;
                paras.ExStyle |= 0x02000000;
                return paras;
            }
        }
        #endregion
    }
}
